<?php
namespace app\api\exception;

use app\admin\model\SystemErrorLog;
use app\facade\Basic;
use think\Exception;
use think\exception\Handle;

use think\facade\Db;
use think\facade\Log;
use think\Request;
use think\Response;
use Throwable;

class ExceptionHandler extends Handle {

    private $statusCode;
    private $message;
    private $code;
    /**
     * Render an exception into an HTTP response.
     *
     * @access public
     * @param \think\Request   $request
     * @param Throwable $e
     * @return Response
     */

    public function render($request, Throwable $e): Response
    {

        /* 添加自定义异常处理机制 */
        if ($e instanceof BaseException) {
            $this->statusCode = $e->statusCode;
            $this->message = $e->message;
            $this->code = $e->code;
            $this->recordErrorLog($request, $e);
        } else {

            /* 全局报错信息 */
            if (env('app_debug')) {
                if (env('app_debug_trace')) {
                    return $this->recordErrorJson($this,$request,$e);
                } else {
                    return parent::render($request, $e);
                }
            } else {
                $this->statusCode = 200;
                $this->message = 'Internal server error';
                $this->code = 0;
                $this->recordErrorLog($request, $e);
            }
        }

        $result = [
            'code' => $this->code,
            'message' => $this->message
        ];

        return json($result,$this->statusCode);

    }

    /**
     *  错误日志处理
     */
    private function recordErrorLog(Request $request, Throwable $e)
    {
        $data['create_time'] = date("Y-m-d H:i:s",time());
        $data['message'] = $e->getMessage();
        $data['method'] = $request->method();
        $data['url'] = $request->request('s');
        $data['type'] = '01';
        $data['file_line'] = $e->getFile().':'.$e->getLine();

        if(count($request->param()) > 0) {
            $data['params'] = json_encode($request->param(),true);
        }

        try {
            /* 记录数据库 */
            Db::name('system_error_log')->save($data);
        } catch (\Exception $e) {
            /* 日志保存失败 记录文件日志 */
            Log::channel('system_error_log')->record($data,'system_error_log');
        }
    }

    /**
     *  自定义错误模板 Json
     */
    private function recordErrorJson($_this,Request $request, Throwable $e)
    {
        $data = [];
        $data['code'] = 1;
        $data['message'] = $e->getMessage();
        $data['method'] = $request->method();
        $data['url'] = $request->request('s');
        $data['httpCode'] = $e->getCode();
        $data['file'] = $e->getFile();
        $data['line'] = $e->getLine();
        return Basic::json($data);
    }

    /**
     *  自定义错误模板
     */
    private function recordErrorHtml(Request $request, Throwable $e)
    {
        $ErrorHtml = <<<HTML
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title> 错误消息 </title>
    </head>
    <body>
       <table>
         <tr>
            <th> 错误信息 </th><th>  </th>
          </tr>
           <tr>
                <td> controller not exists </td>
                <td>{$e->getMessage()}</td>
            </tr>
            <tr>
                <td>URL</td>
                <td>{$request->request('s')}</td>
            </tr>
            <tr>
                <td>method</td>
                <td>{$request->method()}</td>
            </tr>

            <tr>
                <td> http Code </td>
                <td>{$e->getCode()}</td>
            </tr>
            <tr>
                <td> file not found </td>
                <td>{$e->getFile()}</td>
            </tr>
            <tr>
                <td> line number </td>
                <td>{$e->getLine()}</td>
            </tr>

       </table>
    </body>
    </html>
    <style>
       *{
       padding:0;
       margin: 0;
       }
       body {
          background: #232323;
          font-size: 12px;
       }
       body table{
            width: 60%;
            margin: 0 auto;
            margin-top: 100px;
            background: #fff;
            padding: 17px;
            border-radius: 13px;
            text-align: left;
       }

       body table th{
        line-height: 50px;
        margin-bottom: 30px;
       }
       body table td{
            color: #797979;
            line-height: 26px;
       }
       body table td:first-child{
            font-weight: bold;
            color: #6d6d6d;
       }

    </style>
HTML;
        exit($ErrorHtml);
    }
}
